package com.ruoyi.web.controller.kycinfo;

import java.util.*;

import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.kycinfo.domain.*;
import com.ruoyi.kycinfo.dto.KycLabelDTO;
import com.ruoyi.kycinfo.dto.KycUserInfoDTO;
import com.ruoyi.kycinfo.dto.KycUserInfoFilterDTO;
import com.ruoyi.kycinfo.service.*;
import com.ruoyi.kycinfo.service.impl.KycServiceImpl;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.service.impl.SysUserServiceImpl;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;


/**
 * @DESCRIPTION :
 * @date : 2023/10/14 15:17
 */


@RestController
@RequestMapping("/kyc")
public class KycController extends BaseController {
    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private KycServiceImpl kycService;

    @Autowired
    private IKycUserInfoService kycUserInfoService;

    @Autowired
    private IKycFamilyService kycFamilyService;

    @Autowired
    private IKycWorkService kycWorkService;

    @Autowired
    private IKycProductService kycProductService;

    @Autowired
    private IKycPotentialService kycPotentialService;

    @Autowired
    private IKycContactService kycContactService;
    @Autowired
    private IKycFinanceService kycFinanceService;

    @Autowired
    private IKycLabelService kycLabelService;

    @ApiOperation("自定义kyc客户标签")
    @PostMapping("/addLabel")
    public AjaxResult addLabel(@RequestBody @ApiParam("自定义kyc客户标签") KycLabelDTO kycLabelDTO) {
        List<Long> userInfoIdList = kycLabelDTO.getUserInfoIdList();
        String label = kycLabelDTO.getLabel();
        // 获取当前的用户信息
        LoginUser loginUser = SecurityUtils.getLoginUser();
        // 获取当前用户ID
        Long userId = loginUser.getUserId();
        int count = 0;
        for (Long userInfoId : userInfoIdList) {
            KycLabel kycLabel = new KycLabel();
            kycLabel.setUserId(userId);
            kycLabel.setUserInfoId(userInfoId);
            kycLabel.setLabel(label);
            kycLabelService.insertKycLabel(kycLabel);
            count++;
        }

        return toAjax(count);
    }

    @ApiOperation("根据登陆用户，查询当前登陆用户的自定义客户标签，能查询到多条数据")
    @GetMapping(value = "/labels")
    public HashSet<String> getSysUserKycLabels() {
        // 获取当前用户ID
        Long userId = SecurityUtils.getUserId();

        HashSet<String> labelSet = new HashSet<>();
        KycLabel kycLabel = new KycLabel();
        kycLabel.setUserId(userId);
        List<KycLabel> kycLabels = kycLabelService.selectKycLabelList(kycLabel);
        for (KycLabel label : kycLabels) {
            labelSet.add(label.getLabel());
        }
        return labelSet;
    }

    /*
     * 根据user_id 查询 KycUserInfo 能查询到多条数据
     *       一个支行客户岗，有多个自己的客户，一条客户信息，对应一个KycUserInfo，
     * */
    @ApiOperation("根据userId和label 查询 KycUserInfo对象信息,能查询到多条数据")
    @GetMapping(value = "/label/{label}")
    public TableDataInfo getKycUserInfoByKycLabel(@ApiParam("label") String label) {
        // 权限
        List<KycUserInfo> list = new ArrayList<>();
        List<Long> userInfoIdList = kycService.selectKycUserInfoIdList();

        if (userInfoIdList.size() == 0) {
            return getDataTable(list);
        }

        // 获取当前登陆用户的userId
        LoginUser loginUser = SecurityUtils.getLoginUser();
        Long curUserId = loginUser.getUserId();

        // 获取label,查询kycLable列表，提取出userInfoId列表
        KycLabel kycLabel = new KycLabel();
        kycLabel.setUserId(curUserId);
        kycLabel.setLabel(label);
        List<KycLabel> kycLabels = kycLabelService.selectKycLabelList(kycLabel);
        List<Long> labelUserInfoIdList = new ArrayList<>();
        for (KycLabel kycLabel1 : kycLabels) {
            labelUserInfoIdList.add(kycLabel1.getUserInfoId());
        }

        // 根据userInfoId列表查询KycUserInfo列表，分页返回
        labelUserInfoIdList.retainAll(userInfoIdList);
        startPage();
        list = kycUserInfoService.selectKycUserInfoListByUserInfoIdList(labelUserInfoIdList);

        return getDataTable(list);
    }

    @ApiOperation("用户在线填写kyc信息表提交数据")
    @PostMapping("/insert")
    public AjaxResult add(@Validated @RequestBody @ApiParam("kyc信息表数据") KycUserInfoDTO kycUserInfoDTO) {
        // 数据校验
        Long userInfoId = kycUserInfoDTO.getKycUserInfo().getUserInfoId();
        KycUserInfo userInfo = kycUserInfoService.selectKycUserInfoByUserInfoId(userInfoId);
        if (userInfo != null) {
            // 用户输入的客户号用户信息已经存在，返回错误信息
            return error("新增客户号'" + userInfoId + "'失败，客户号用户信息已存在");
        }

        // 获取当前的用户信息
        LoginUser loginUser = SecurityUtils.getLoginUser();
        // 获取当前用户ID
        Long userId = loginUser.getUserId();
        kycUserInfoDTO.getKycUserInfo().setUserId(userId);

        return toAjax(kycService.insertKycInfo(kycUserInfoDTO));
    }

    /*
     * 根据user_id 查询 KycUserInfo 能查询到多条数据
     *       一个支行客户岗，有多个自己的客户，一条客户信息，对应一个KycUserInfo，
     * */
    @ApiOperation("根据user_id 查询 KycUserInfo对象信息,能查询到多条数据")
    @GetMapping(value = "/userinfo/{userId}")
    public AjaxResult getKycUserInfoByUserId(@PathVariable("userId") @ApiParam("userId") Long userId) {
        return success(kycUserInfoService.selectKycUserInfoListByUserId(userId));
    }

    /*
     * 根据user_info_id 查询 KycFamily 可以查询到多条数据
     * */
    @ApiOperation("根据user_info_id 查询 KycFamily对象信息,可以查询到多条数据")
    @GetMapping(value = "/family/{userInfoId}")
    public AjaxResult getKycFamilyListByUserInfoId(@PathVariable("userInfoId") @ApiParam("userInfoId") Long userInfoId) {
        return success(kycFamilyService.selectKycFamilyListByUserInfoId(userInfoId));
    }

    /*
     * 根据user_info_id 查询 KycWork对象信息 只能查询到一条数据
     * */
    @ApiOperation("根据user_info_id 查询 KycWork对象信息,能查询到一条数据")
    @GetMapping(value = "/work/{userInfoId}")
    public AjaxResult selectKycWorkByUserInfoId(@PathVariable("userInfoId") @ApiParam("userInfoId") Long userInfoId) {
        KycWork kycWork = kycWorkService.selectKycWorkByUserInfoId(userInfoId);
        if (kycWork == null) {
            kycWork = new KycWork();
            kycWork.setWorkId(0L);
            kycWork.setUserInfoId(userInfoId);
//            System.out.println("kycWork客户号设置成功！！");
        }
        return success(kycWork);
    }

    /*
     * 根据user_info_id 查询 KycFinance对象信息 只能查询到一条数据
     * */
    @ApiOperation("根据user_info_id 查询 KycFinance对象信息,能查询到一条数据")
    @GetMapping(value = "/finance/{userInfoId}")
    public AjaxResult selectKycFinanceByUserInfoId(@PathVariable("userInfoId") @ApiParam("userInfoId") Long userInfoId) {
        KycFinance kycFinance = kycFinanceService.selectKycFinanceByUserInfoId(userInfoId);
        if (kycFinance == null) {
            kycFinance = new KycFinance();
            kycFinance.setFinanceId(0L);
            kycFinance.setUserInfoId(userInfoId);
//            System.out.println("kycFinance客户号设置成功！！");
        }
        return success(kycFinance);
    }


    /*
     * 根据user_info_id 查询 KycProduct对象信息 只能查询到一条数据
     * */
    @ApiOperation("根据user_id 查询 KycProduct对象信息,能查询到一条数据")
    @GetMapping(value = "/product/{userInfoId}")
    public AjaxResult getKycProductByUserInfoId(@PathVariable("userInfoId") @ApiParam("userInfoId") Long userInfoId) {
        KycProduct kycProduct = kycProductService.selectKycProductByUserInfoId(userInfoId);
        if (kycProduct == null) {
            kycProduct = new KycProduct();
            kycProduct.setProductId(0L);
            kycProduct.setUserInfoId(userInfoId);
//            System.out.println("kycProduct客户号设置成功！！");
        }
        return success(kycProduct);
    }

    /*
     * 根据user_info_id 查询 KycPotential对象信息 可以查询到多条数据
     * */
    @ApiOperation("根据user_info_id 查询 KycPotential对象信息,可以查询到多条数据")
    @GetMapping(value = "/potential/{userInfoId}")
    public AjaxResult getKycPotentialListByUserInfoId(@PathVariable("userInfoId") @ApiParam("userInfoId") Long userInfoId) {
        return success(kycPotentialService.selectKycPotentialListByUserInfoId(userInfoId));
    }

    /*
     * 根据user_id 查询 KycContact对象信息 可以查询到多条数据
     * */
    @ApiOperation("根据user_info_id 查询 KycContact对象信息,可以查询到多条数据")
    @GetMapping(value = "/contact/{userInfoId}")
    public AjaxResult getKycContactListByUserInfoId(@PathVariable("userInfoId") @ApiParam("userInfoId") Long userInfoId) {
        return success(kycContactService.selectKycContactListByUserInfoId(userInfoId));
    }

    /*
     * updateSupport 参数：如果客户信息已经存在，是否进行客户信息更新
     * */
    @ApiOperation("导入KYC表格数据")
    @PostMapping("/importData")
    public AjaxResult importData(@ApiParam("excel文件") MultipartFile file, @ApiParam("updateSupport") boolean updateSupport) throws Exception {
        // 获取当前的用户信息
        LoginUser loginUser = SecurityUtils.getLoginUser();
        // 获取当前用户ID
        Long userId = loginUser.getUserId();
        String message = kycUserInfoService.importKycInfo(userId, updateSupport, file.getInputStream());

        return AjaxResult.success(message);
    }

    /*
     * 根据输入的指定的用户编号，查询该用户的直接客户，将客户信息的 客户号，用户编号 导出为excel文件
     * */
    @ApiOperation("导出客户数据")
    @PostMapping("/userInfoExport")
    public void export(HttpServletResponse response, KycUserInfo kycUserInfo) {
        // 根据用户编号导出客户信息，查询结果唯一
        ExcelUtil<KycUserInfo> util = new ExcelUtil<>(KycUserInfo.class);
        boolean flag = false;

        SysUser findUser = sysUserService.selectUserById(kycUserInfo.getUserId());
        // 如果输入的用户编号错误，则导出一个空的文件
        if (findUser == null) {
            util.exportExcel(response, new ArrayList<>(), "输入的用户编号信息不存在，请检查您输入的用户编号");
        } else {
            // 校验：当前登陆用户是否有权限访问该编号用户的客户信息
            // 权限校验，例如A支行的管理岗张三用户，只能导出A支行的支行用户的客户信息
            // 可能输入的是自己的用户编号
            // 判断输入的用户编号是否等于当前登陆用户自己的用户编号
            if (findUser.getUserId() == SecurityUtils.getUserId()) {
                flag = true;
            } else {
                // 输入的是其他用户的用户编号，进行用户权限校验
                List<SysUser> sysUsers = sysUserService.selectUserList(new SysUser());
                for (SysUser user : sysUsers) {
                    if (user.getUserId() == findUser.getUserId()) {
                        flag = true;
                        break;
                    }
                }
            }

            if (flag) {
                List<KycUserInfo> list = kycUserInfoService.selectKycUserInfoListByUserId(findUser.getUserId());
                util.exportExcel(response, list, "客户数据");
            } else {
                util.exportExcel(response, new ArrayList<>(), "您没有权限访问该编号用户的客户信息");
            }
        }
    }

    @ApiOperation("导入KYC金融信息")
    @PostMapping("/importFinanceData")
    public AjaxResult importFinanceData(@ApiParam("excel文件") MultipartFile file, @ApiParam("updateSupport") boolean updateSupport) throws Exception {
        String message = kycFinanceService.importKycFinance(updateSupport, file.getInputStream());

        return AjaxResult.success(message);
    }

    @ApiOperation("导入KYC客户所属客户经理变更信息")
    @PostMapping("/importChangeData")
    public AjaxResult importChangeData(@ApiParam("excel文件") MultipartFile file) throws Exception {
        // 变更客户关系时，进行权限校验，例如铁西支行管理岗，只能变更本支行的客户关系，不能变更其他支行的客户关系
        String message = kycUserInfoService.importKycInfoChange(file.getInputStream());

        return AjaxResult.success(message);
    }

    /**
     * kycUserInfo多条件筛选
     * 单选框，复选框
     */
    @ApiOperation("kycUserInfo多条件筛选")
    @PreAuthorize("@ss.hasPermi('kycinfo:userinfo:list')")
    @GetMapping("/list")
    public TableDataInfo list(@ApiParam("筛选条件封装对象") KycUserInfoFilterDTO userInfoFilterDTO) {
        List<KycUserInfo> list = new ArrayList<>();
        // 查询当前登陆用户所能访问到的所有客户的 客户号，例如：铁西支行管理岗查询结果为：铁西支行管理岗和所有铁西支行用户岗的客户们的客户号
        List<Long> userInfoIdList = kycService.selectKycUserInfoIdList();

        if (userInfoIdList.size() == 0) {
            return getDataTable(list);
        }

        String nickName = userInfoFilterDTO.getNickName();
        // 根据输入的用户昵称进行查询
        // 需要对输入的用户昵称进行权限校验，例如：铁西支行管理岗，搜索香港路支行的用户昵称结果应该为空
        if (!StringUtils.isEmpty(nickName)) {
            // 根据nickName查询指定的银行用户
            List<Long> nickNameUserIdList = new ArrayList<>();
            List<Long> nickNameUserInfoIdList = new ArrayList<>();
            List<SysUser> sysUsers = sysUserService.selectUserByNickName(nickName);
            for (SysUser sysUser : sysUsers) {
                nickNameUserIdList.add(sysUser.getUserId());
            }
            List<KycUserInfo> kycUserInfos = kycUserInfoService.selectKycUserInfoListByUserIdList(nickNameUserIdList);
            for (KycUserInfo userInfo : kycUserInfos) {
                nickNameUserInfoIdList.add(userInfo.getUserInfoId());
            }
            // 对查询到的客户号，进行用户昵称查询的过滤，缩小查询范围
            userInfoIdList.retainAll(nickNameUserInfoIdList);
        }

        // 根据用户标签查询客户
        String label = userInfoFilterDTO.getLabel();
        // 对 label字段进行判空
        if (!StringUtils.isEmpty(label)) {
            // 获取当前用户ID
            Long loginUserId = SecurityUtils.getUserId();
            // 获取label,查询kycLable列表，提取出userInfoId列表
            KycLabel kycLabel = new KycLabel();
            kycLabel.setUserId(loginUserId);
            kycLabel.setLabel(label);
            List<KycLabel> kycLabels = kycLabelService.selectKycLabelList(kycLabel);
            List<Long> labelUserInfoIdList = new ArrayList<>();
            for (KycLabel kycLabel1 : kycLabels) {
                labelUserInfoIdList.add(kycLabel1.getUserInfoId());
            }
            // 对查询到的客户号，进行客户标签查询的过滤，缩小查询范围
            userInfoIdList.retainAll(labelUserInfoIdList);
        }

        if(userInfoIdList.size()==0){
            // 如果查询结果为空，直接返回一个空的查询结果，以免执行语句会不走多条件过滤查询，进行无条件查询
            return getDataTable(list);
        }
        // 设置可以查询到的 UserInfoId列表
        userInfoFilterDTO.setUserInfoIdList(userInfoIdList);
        // 如果这里的userInfoIdList为空，也就是查询结果为空，下面的执行语句会不走多条件过滤查询，进行无条件查询

        startPage();
        list = kycService.selectKycUserInfoList(userInfoFilterDTO);
        return getDataTable(list);
    }

}